

import AVFoundation
import NaturalLanguage
import UIKit
import Alamofire
import SwiftEventBus

// MARK: - ChatViewController

/// A base class for the example controllers
class BasicChatViewController: MessagesViewController, MessagesDataSource,UITextViewDelegate {
    let synthVM = SynthViewModel()
   
    var needContext = false
    let languageRecognizer = NLLanguageRecognizer()
    var isAnswer = false
    var roleDescription = ""
    var rolePrompt: String = ""
    var pageTitle: String = "AI聊天"
    var inputHint: String = "您的任何问题"
    var type = -1
    
    // MARK: Internal
    
    // MARK: - Public properties
    var retques: DataStreamRequest?
    /// The `BasicAudioController` control the AVAudioPlayer state (play, pause, stop) and update audio cell UI accordingly.
    lazy var audioController = BasicAudioController(messageCollectionView: messagesCollectionView)
    
    lazy var messageList: [MockMessage] = []
    
        
    // MARK: - MessagesDataSource
    
    var currentSender: SenderType {
        MockUser(senderId: senderId, displayName: senderName)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = primaryDarkBackgroundColor
        navigationItem.title = pageTitle
        WXNavigationBar.NavBar.tintColor = .darkText
        configureMessageCollectionView()
        configureMessageInputBar()
        let senderDate = Date()
        
        let okButton = UIBarButtonItem(image: UIImage(named: "ic_goforward"), style: .done, target: self, action: #selector(handleokButtonClicked))
        
        navigationItem.rightBarButtonItem = okButton
        if type != -1{
                                    
            
            let receiveMessage = MockMessage(text: roleDescription, user:  MockUser(senderId: receiverId, displayName: senderName), messageId: "\(messageList.count)", date: senderDate)
            insertMessage(receiveMessage)
            
        }else{
            //首页
            let receiveMessage = MockMessage(text: StoreManager.getHomeChatDescription(), user:  MockUser(senderId: receiverId, displayName: senderName), messageId: "\(messageList.count)", date: senderDate)
            insertMessage(receiveMessage)
            rolePrompt = StoreManager.getHomeChatPrompt()
            navigationItem.title = StoreManager.getHomeChatTitle()
            
            SwiftEventBus.onMainThread(self, name: EVENT_NAME_UPDATE_HOME_ROLE) { result in
                self.navigationItem.title = StoreManager.getHomeChatTitle()
                self.messageList.remove(at: 0)
                
                let receiveMessage = MockMessage(text: StoreManager.getHomeChatDescription(), user:  MockUser(senderId: receiverId, displayName: senderName), messageId: "\(self.messageList.count)", date: senderDate)
                
                self.messageList.insert(receiveMessage, at: 0)
                self.messagesCollectionView.reloadData()
            }
        }
        
        
        
        
        
    }
    
    @objc private func handleTap(_ sender: Any) {
        self.view.endEditing(true)
        print("handleTap")
        
    }
    
    override var wx_titleTextAttributes: [NSAttributedString.Key : Any]? {
        return [NSAttributedString.Key.foregroundColor: UIColor.darkText]
    }
    
    @objc private func handleCancelButtonClicked() {
        self.navigationController?.popViewController(animated: true)
    }
    
    @objc  func handleokButtonClicked() {

        
        self.needContext = false
        self.view.makeToast("已开启新的对话",position: .center)
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        audioController.stopAnyOngoingPlaying()
    }
    
    
    func configToSendButton(){
        messageInputBar.sendButton.imageView?.backgroundColor = .black.withAlphaComponent(0.15)
        messageInputBar.sendButton.contentEdgeInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
        messageInputBar.sendButton.setSize(CGSize(width: 36, height: 36), animated: false)
        messageInputBar.sendButton.image = #imageLiteral(resourceName: "ic_up")
        messageInputBar.sendButton.title = nil
        messageInputBar.sendButton.imageView?.layer.cornerRadius = 16
        messageInputBar.sendButton.isEnabled = false
        isAnswer = false
        self.setTypingIndicatorViewHidden(true, animated: true)
    }
    
    func configToStopButton(){
        messageInputBar.sendButton.contentEdgeInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
        messageInputBar.sendButton.setSize(CGSize(width: 36, height: 36), animated: false)
        messageInputBar.sendButton.image = #imageLiteral(resourceName: "ic_stop")
        messageInputBar.sendButton.title = nil
        messageInputBar.sendButton.tintColor = UIColor.white
        messageInputBar.sendButton.isEnabled = true
        isAnswer = true
    }
    
    
    func configureMessageCollectionView() {
        messagesCollectionView.backgroundColor = primaryDarkBackgroundColor
        messagesCollectionView.messagesDataSource = self
        messagesCollectionView.messageCellDelegate = self
        messagesCollectionView.keyboardDismissMode = .onDrag
        scrollsToLastItemOnKeyboardBeginsEditing = true // default false
        maintainPositionOnInputBarHeightChanged = true // default false
        showMessageTimestampOnSwipeLeft = false // default false
        
    }
    
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        if text == "\n"{
            self.view?.endEditing(true)
            return false
        }
        return true
    }
    
    
    func textViewDidEndEditing(_ textView: UITextView) {
        if messageInputBar.inputTextView.text.isEmpty{
            if  messageInputBar.inputTextView.returnKeyType == .send{
                messageInputBar.inputTextView.returnKeyType = .done
                messageInputBar.inputTextView.reloadInputViews()
            }
        }else{
            if  messageInputBar.inputTextView.returnKeyType == .done{
                messageInputBar.inputTextView.returnKeyType = .send
                messageInputBar.inputTextView.reloadInputViews()
            }
        }
        
    }
    
    func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
        if !messageInputBar.inputTextView.text.isEmpty{
            processInputBar(messageInputBar)
        }
        return true
    }
    
    func configureMessageInputBar() {
        messageInputBar.delegate = self
        messageInputBar.inputTextView.keyboardAppearance = .light
        messageInputBar.inputTextView.delegate = self
        messageInputBar.inputTextView.returnKeyType = .send
        messageInputBar.backgroundView.backgroundColor = .white
        messageInputBar.inputTextView.placeholder = inputHint
        messageInputBar.inputTextView.placeholderLabel.font = UIFont.systemFont(ofSize: 15)
        messageInputBar.inputTextView.placeholderTextColor = .black.withAlphaComponent(0.3)
        messageInputBar.inputTextView.tintColor = primaryColor
        messageInputBar.inputTextView.textColor = .darkText
        messageInputBar.separatorLine.height = 0.05

    }
    
    // MARK: - Helpers
    
    func insertMessage(_ message: MockMessage) {
        messageList.append(message)
        
        // Reload last section to update header/footer labels and insert a new one
        messagesCollectionView.performBatchUpdates({
            messagesCollectionView.insertSections([messageList.count - 1])
            if messageList.count >= 2 {
                messagesCollectionView.reloadSections([messageList.count - 2])
            }
        }, completion: { [weak self] _ in
            if self?.isLastSectionVisible() == true {
                self?.messagesCollectionView.scrollToLastItem(animated: true)
            }
        })
    }
    
    func isLastSectionVisible() -> Bool {
        guard !messageList.isEmpty else { return false }
        
        let lastIndexPath = IndexPath(item: 0, section: messageList.count - 1)
        
        return messagesCollectionView.indexPathsForVisibleItems.contains(lastIndexPath)
    }
    
    func numberOfSections(in _: MessagesCollectionView) -> Int {
        messageList.count
    }
    
    func messageForItem(at indexPath: IndexPath, in _: MessagesCollectionView) -> MessageType {
        messageList[indexPath.section]
    }
    
    func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
        
        return nil
    }
    
    
    func cellBottomLabelAttributedText(for message: MessageType, at index: IndexPath) -> NSAttributedString? {
        
        return nil
        
    }
    
    func messageTopLabelAttributedText(for message: MessageType, at _: IndexPath) -> NSAttributedString? {
        
        return nil
    }
    
    //显示当前时间
    func messageBottomLabelAttributedText(for message: MessageType, at _: IndexPath) -> NSAttributedString? {
        
        
        let dateString = formatter.string(from: message.sentDate)
        return NSAttributedString(
            string: dateString,
            attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption2),NSAttributedString.Key.foregroundColor: isFromCurrentSender(message: message) ? UIColor.white : UIColor.gray])
    }
    
    func textCell(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UICollectionViewCell? {
        nil
    }
        
    // MARK: - Private properties
    
    private let formatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter
    }()
}

// MARK: MessageCellDelegate

extension BasicChatViewController: MessageCellDelegate {
    func didTapAvatar(in _: MessageCollectionViewCell) {
        print("Avatar tapped")
    }
    
    func didTapMessage(in _: MessageCollectionViewCell) {
        print("Message tapped")
    }
    
    func didTapImage(in _: MessageCollectionViewCell) {
        print("Image tapped")
    }
    
    func didTapCellTopLabel(in _: MessageCollectionViewCell) {
        print("Top cell label tapped")
    }
    
    func didTapCellBottomLabel(in _: MessageCollectionViewCell) {
        print("Bottom cell label tapped！！！！！！！！！！！！！！！！！！！！")
        self.view.endEditing(true)
        
    }
    
    func didTapMessageTopLabel(in _: MessageCollectionViewCell) {
        print("Top message label tapped")
    }
    
//    func didTapMessageBottomLabel(in _: MessageCollectionViewCell) {
//        print("Bottom label tapped~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
//        let msg = "继续"
//        let senderDate = Date()
//        let message = MockMessage(text: msg, user:  MockUser(senderId: senderId, displayName: senderName), messageId: "\(self.messageList.count)", date: senderDate)
//        insertMessage(message)
//        self.setTypingIndicatorViewHidden(false, animated: true)
//        startSSE(prompt: msg, rolePrompt: rolePrompt,senderDate: senderDate)
//    }
    
    func didTapPlayButton(in cell: AudioMessageCell) {
        guard
            let indexPath = messagesCollectionView.indexPath(for: cell),
            let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
        else {
            print("Failed to identify message when audio cell receive tap gesture")
            return
        }
        guard audioController.state != .stopped else {
            // There is no audio sound playing - prepare to start playing for given audio message
            audioController.playSound(for: message, in: cell)
            return
        }
        if audioController.playingMessage?.messageId == message.messageId {
            // tap occur in the current cell that is playing audio sound
            if audioController.state == .playing {
                audioController.pauseSound(for: message, in: cell)
            } else {
                audioController.resumeSound()
            }
        } else {
            // tap occur in a difference cell that the one is currently playing sound. First stop currently playing and start the sound for given message
            audioController.stopAnyOngoingPlaying()
            audioController.playSound(for: message, in: cell)
        }
    }
    
    func didStartAudio(in _: AudioMessageCell) {
        print("Did start playing audio sound")
    }
    
    func didPauseAudio(in _: AudioMessageCell) {
        print("Did pause audio sound")
    }
    
    func didStopAudio(in _: AudioMessageCell) {
        print("Did stop audio sound")
    }
    
    func didTapAccessoryView(in _: MessageCollectionViewCell) {
        print("Accessory view tapped")
    }
}

// MARK: MessageLabelDelegate

extension BasicChatViewController: MessageLabelDelegate {
    func didSelectAddress(_ addressComponents: [String: String]) {
        print("Address Selected: \(addressComponents)")
    }
    
    func didSelectDate(_ date: Date) {
        print("Date Selected: \(date)")
    }
    
    func didSelectPhoneNumber(_ phoneNumber: String) {
        print("Phone Number Selected: \(phoneNumber)")
    }
    
    func didSelectURL(_ url: URL) {
        print("URL Selected: \(url)")
    }
    
    func didSelectTransitInformation(_ transitInformation: [String: String]) {
        print("TransitInformation Selected: \(transitInformation)")
    }
    
    func didSelectHashtag(_ hashtag: String) {
        print("Hashtag selected: \(hashtag)")
    }
    
    func didSelectMention(_ mention: String) {
        print("Mention selected: \(mention)")
    }
    
    func didSelectCustom(_ pattern: String, match _: String?) {
        print("Custom data detector patter selected: \(pattern)")
    }
}

// MARK: InputBarAccessoryViewDelegate

extension BasicChatViewController: InputBarAccessoryViewDelegate {

    @objc
    func inputBar(_: InputBarAccessoryView, didPressSendButtonWith _: String) {
        processInputBar(messageInputBar)
    }
    
    func processInputBar(_ inputBar: InputBarAccessoryView) {
      
        
        if isAnswer{
            configToSendButton()
            //如果还没开始回答 赋值“已停止回答。”
        }else{
            
            let components = inputBar.inputTextView.components
            inputBar.inputTextView.text = String()
            inputBar.invalidatePlugins()
            // Send button activity animation
            //        inputBar.sendButton.startAnimating()
            configToStopButton()
            
            inputBar.inputTextView.placeholder = "对话中..."
            // Resign first responder for iPad split view
            inputBar.inputTextView.resignFirstResponder()
            //        startSSE(prompt: inputBar.inputTextView.text, rolePrompt: "")
            insertMessages(components)
            //        inputBar.sendButton.stopAnimating()
            //        inputBar.inputTextView.placeholder = "与AI对话"
        }
        
    }
    
    // MARK: Private
    
    private func insertMessages(_ data: [Any]) {
        for component in data {
            //      let user = SampleData.shared.currentSender
            if let str = component as? String {
                let senderDate = Date()
                let message = MockMessage(text: str, user:  MockUser(senderId: senderId, displayName: senderName), messageId: "\(self.messageList.count)", date: senderDate)
                insertMessage(message)
                self.setTypingIndicatorViewHidden(false, animated: true)
                startSSE(prompt: str, rolePrompt: rolePrompt,senderDate: senderDate)
                
            } else if let img = component as? UIImage {
                let message = MockMessage(image: img, user:  MockUser(senderId: senderId, displayName: senderName), messageId: UUID().uuidString, date: Date())
                insertMessage(message)
            }
        }
    }
    
    
    func stopSSE(){
        if let request = self.retques{
            print("stop sse")
            request.cancel()
            if StoreManager.isVoiceOpen(){
                self.synthVM.stop()
            }
        }
    }
    
    func updateMsg(index: Int,msgIndex: Int){
        UICollectionView.performWithoutAnimation {
            self.messagesCollectionView.reloadItems(at: [IndexPath(index: index)])
        }
        
        
        if msgIndex % 8 == 0{
            if !self.isLastSectionVisible(){
                self.messagesCollectionView.scrollToLastItem(animated: true)
            }
        }
        
        
    }
    func startSSE(prompt: String,rolePrompt: String, senderDate: Date) {
        
        
        var components = URLComponents(string: "\(baseUrl)chatgpt/chat/sseV2")
        
        
        // 创建URL参数
        let promptItem = URLQueryItem(name: "prompt", value: prompt)
        let rolePromptItem = URLQueryItem(name: "rolePrompt", value: rolePrompt)
        let needContextItem = URLQueryItem(name: "needContext", value: "\(self.needContext)")
        
        
        // 将URL参数添加到URLComponents对象中
        components?.queryItems = [promptItem,rolePromptItem,needContextItem]
        
        
        var receivedData = ""
        var msgIndex = 0
        
        if let url = components?.url {
            // 使用拼接好的URL进行网络请求或其他操作
            print("startSSEstartSSEstartSSE:\(prompt)")
            
            
            self.retques = AFManager.sharedInstance.manager.eventSourceRequest(url, lastEventID: "0").responseEventSource { eventSource in
                switch eventSource.event {
                case .message(let message):
                    
                    if let msg = message.data{
                        
                        msgIndex += 1
                        if msg.isChinese(){
                            print("isChinese:true")
                            receivedData.append("\(msg)")
                        }else{
                            print("isChinese:false")
                            receivedData.append("\(msg) ")
                        }
                        
                        if receivedData.contains(wxb){
                            receivedData = wxb
                        }
                        if msgIndex == 1{
                            let message = MockMessage(text: receivedData, user:  MockUser(senderId: receiverId, displayName: senderName), messageId: "\(self.messageList.count)", date: senderDate)
                            self.insertMessage(message)
                            self.setTypingIndicatorViewHidden(true, animated: true)
                        }else{
                            if let index = self.messageList.lastIndex(where: { $0.sentDate == senderDate }) {
                                self.messageList[index].kind = .text(receivedData)
                                self.updateMsg(index: index,msgIndex: msgIndex)
                                
                            }
                        }
                        
                        if StoreManager.isVoiceOpen(){
                            self.synthVM.addTextToSpeech(text: msg)
                            if msgIndex == 1{
                                self.synthVM.speak()
                            }
                        }
                        
                    }else{
                        if receivedData != ""{
                            if !receivedData.hasSuffix("\n"){
                                receivedData.append("\n")
                            }
                        }
                    }
                    print("msg=\(message)")
                case .complete(_):
                    
                    self.needContext = true
                    self.configToSendButton()
                    self.messageInputBar.inputTextView.placeholder = "您的任何问题"
                    if let index = self.messageList.lastIndex(where: { $0.sentDate == senderDate }) {
                        UICollectionView.performWithoutAnimation {
                            self.messagesCollectionView.reloadItems(at: [IndexPath(index: index)])
                        }
                        
                    }
                    self.messagesCollectionView.scrollToLastItem(animated: true)
                    if receivedData.contains("免费提问次数已用完"){
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1){
                            let detailViewController = VipViewController()
                            detailViewController.fromPage = "聊天-\(prompt)"
                            self.navigationController?.pushViewController(detailViewController, animated: true)
                        }
                        
                    }
                    print("completion")
                }
            }
        }
    }
}
extension String{
    func isChinese() -> Bool{
        if "\u{4E00}" <= self  && self <= "\u{9FA5}" {
            return true
        }
        return false
    }
}


//文字转语音模块
class SynthViewModel: NSObject {
    var isSpeaking = false
    var answerComplete: Bool = false
    private var speechSynthesizer = AVSpeechSynthesizer()
    var textWillSpeech = ""
    let languageRecognizer = NLLanguageRecognizer()
    var onSpeakComplete: (() -> Void)!
    var isManualStop = false
    override init() {
        super.init()
        self.speechSynthesizer.delegate = self
    }
    

    func addTextToSpeech(text: String){
        self.isSpeaking = true
        textWillSpeech.append(text)
    }
    //第一次开始时调用
    func speak() {
        answerComplete = false
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            print("text to speech=first")
            self.speak(text: self.textWillSpeech)
            self.textWillSpeech = ""
        }
    }
    //只有手动重新播放才会外部调用
    func speak(text:String) {
        
        if text !=  ""{
            
            let utterance = AVSpeechUtterance(string: text)
            utterance.pitchMultiplier = 1.0
            utterance.rate = 0.52
            utterance.volume = 0.5
            self.languageRecognizer.processString(text)
            
            if let dominantLanguage = self.languageRecognizer.dominantLanguage {
                print("language=\(dominantLanguage.rawValue)")
                utterance.voice = AVSpeechSynthesisVoice(language: dominantLanguage.rawValue)
            }else{
                utterance.voice = AVSpeechSynthesisVoice(language: "zh-CN")
            }
            print("text to speech=\(text)")
            
            self.speechSynthesizer.speak(utterance)
        }
        
    }
    
    

    func stop() {
        self.isSpeaking = false
        print("stop immediate")
        speechSynthesizer.stopSpeaking(at: .immediate)
        
    }
    
    func pause() {
        self.isSpeaking = false
        print("pause immediate")
        speechSynthesizer.pauseSpeaking(at: .immediate)
    }
    
    func isPaused()->Bool {
        return  speechSynthesizer.isPaused
    }
    
    func continueSpeaking() {
        print("continueSpeaking")
        self.isSpeaking = true
        speechSynthesizer.continueSpeaking()
    }
}

extension SynthViewModel: AVSpeechSynthesizerDelegate {
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
        print("text to speech started")
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .videoChat,options: .defaultToSpeaker)
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print("avAudioSesseion error")
        }
    }
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) {
        print("text to speech paused")
        
    }
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) {}
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {}
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) {}
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        print("text to speech finished textWillSpeech=\(textWillSpeech)")
        do{
            try  AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .videoChat, options: .interruptSpokenAudioAndMixWithOthers)
            try  AVAudioSession.sharedInstance().setActive(true)
        }catch{
            print("ERROR: - Audio Session Failed!")
        }
        if !isManualStop{//手动停止不做任何处理，如果只是完成了一小段，则继续把剩余的textWillSpeech 读完
            if textWillSpeech != ""{
                print("text to speech continue")
                self.speak(text: textWillSpeech)
                textWillSpeech = ""
            }else{
                //如果answerComplete是false 需要特殊处理
//                if !answerComplete{
//                    //定时查询有没有数据过来，一旦有则继续播放,取消定时
//
//                }else{
                    //暂且认为播放完成
                self.isSpeaking = false
//                    onSpeakComplete()
//                }
                
                
            }
        }
    }
}

